#ifndef FACTORY_CORE_H_
#define FACTORY_CORE_H_

#include <BlockingQueue.hh>
#include "Group.hh"
#include "GroupWorker.hh"
#include "Stopwatch.hh"

//
/**
 * \file FactoryCore.hh
 * \author  jsk <jsk.jinsubkim@gmail.com>
 * \version 1.0
 *
 * \class FactoryCore FactoryCore.hh
 *
 * 한 태스크 큐를 공유하는 워커를 관리한다.
 * 
 * 펙토리에 포함된 워커들은 한 리스트에 포함된다. 그리고 최소 워커 개수를 
 * 유지하고, 최대 워커 개스를 넘지않는다.
 * 
 * run 메소드로 펙트로리를 가동시키면 최소 워커 개수만큼 생성되고, 
 * fetchTask 메소드로 작업을 할당하고, 만약 가용한 워커가 없다면, 워커를 
 * 생성하고, stop 메소드로 펙토리를 중단할 때 할당 받은 작업을 모두 처리한다.
 */
class FactoryCore
{
public:
	/**
	 * \name FactoryCore
	 * \param AssignedGroup 펙토리의 정보를 관리하는 클래스 인스턴스.
	 */
	FactoryCore(BlockingQueue* AssignedQueue, Group* AssignedGroup);
	
	/**
	 * \name run
	 * \param Min 최소 워커 개수.
	 * \param Max 최대 워커 개수.
	 * 
	 * 펙토리를 가동한다.
	 * 
	 * \return 
	 * 
	 * 성공할 경우 RETURN_OK, 
	 * 실패할 경우 RETURN_OK가 아닌 값.
	 */
	virtual ResultOf run(USNumber Min, USNumber Max);
	
	/**
	 * \name stop
	 * 
	 * 펙토리를 중지시킨다.
	 * 
	 * \return 
	 * 
	 * 성공할 경우 RETURN_OK, 
	 * 실패할 경우 RETURN_OK가 아닌 값.
	 */
	virtual ResultOf stop();
	
	/**
	 * \name adjustNumOfWorker
	 * \param Min 최소 워커 개수.
	 * \param Max 최대 워커 개수.
	 * 
	 * 워커의 개수를 조정한다.
	 * 
	 * \return 
	 * 
	 * 성공할 경우 RETURN_OK, 
	 * 실패할 경우 RETURN_OK가 아닌 값.
	 */
	virtual ResultOf adjustNumOfWorker(USNumber Min, USNumber Max);
	
	/**
	 * \name fetchTask
	 * 
	 * 작업을 할당한다.
	 * 
	 * 큐에 할당 받은 작업을 넣는다.
	 * 
	 * \return 
	 * 
	 * 성공할 경우 RETURN_OK, 
	 * 실패할 경우 RETURN_OK가 아닌 값.
	 */
	virtual ResultOf fetchTask(Task* NewTask);
	
	/**
	 * \name setIntervalOfWatchdog
	 * \param Interval 감시 주기(마이크로 초). 
	 * 
	 * 감시 주기를 설정한다.
	 * 
	 * \return 
	 * 
	 * 성공할 경우 RETURN_OK, 
	 * 실패할 경우 RETURN_OK가 아닌 값.
	 */
	virtual ResultOf setIntervalOfWatchdog(USNumber Interval);
	
	/**
	 * \name tellNumOfEmployee
	 * 
	 * 현재 워커(GroupWorker)의 개수를 알려준다.
	 * 
	 * \return 
	 * 
	 * 펙토리에 포함된 워커(GroupWorker)의 개수.
	 */
	virtual USNumber tellNumOfEmployee();
	
// Factory
protected:
	/**
	 * \name adjustNumOfWorker_
	 * \param Min 최소 워커 개수.
	 * \param Max 최대 워커 개수.
	 * 
	 * 워커의 개수를 조절한다.
	 * 
	 * \return 
	 * 
	 * 성공할 경우 RETURN_OK, 
	 * 실패할 경우 RETURN_OK가 아닌 값.
	 */
	virtual ResultOf adjustNumOfWorker_(USNumber Min, USNumber Max);
	
// Watchdog
protected:
	/**
	 * \name startWatchdog
	 * 
	 * Watchdog를 시작한다.
	 * 
	 * \return 
	 * 
	 * 성공할 경우 RETURN_OK, 
	 * 실패할 경우 RETURN_OK가 아닌 값.
	 */
	virtual ResultOf startWatchdog();
	
	/**
	 * \name stopWatchdog
	 * 
	 * Watchdog를 종료한다.
	 * 
	 * \return 
	 * 
	 * 성공할 경우 RETURN_OK, 
	 * 실패할 경우 RETURN_OK가 아닌 값.
	 */
	virtual ResultOf stopWatchdog();
	
	/**
	 * \name ThreadFunc
	 * \param This 자신의 인스턴스 주소.
	 * 
	 * Watchdog의 시작 루틴.
	 * 
	 * \return 
	 * 
	 * 항상 NULL.
	 */
	static void* ThreadFunc(void* This);
	
	/**
	 * \name watch
	 * 
	 * 펙토리의 상태를 감시한다.
	 * 
	 * \return 
	 * 
	 * 성공할 경우 RETURN_OK, 
	 * 실패할 경우 RETURN_OK가 아닌 값.
	 */
	virtual ResultOf watch();
	
	/**
	 * \name hookWatchdog
	 * 
	 * ???
	 * 
	 * \return 
	 * 
	 * 성공할 경우 RETURN_OK, 
	 * 실패할 경우 RETURN_OK가 아닌 값.
	 */
	virtual ResultOf hookWatchdog();
	
// Worker
protected:
	/**
	 * \name employ
	 * 
	 * 워커를 생성한다.
	 * 
	 * \return 
	 * 
	 * 성공할 경우 RETURN_OK, 
	 * 실패할 경우 RETURN_OK가 아닌 값.
	 */
	virtual ResultOf employ();
	
	/**
	 * \name fire
	 * 
	 * 워커를 제거한다.
	 * 
	 * 리스트에서 특정 워커의 주소를 알아내고, fire 메소드를 호출한다.
	 * 
	 * \return 
	 * 
	 * 성공할 경우 RETURN_OK, 
	 * 실패할 경우 RETURN_OK가 아닌 값.
	 */
	virtual ResultOf fire();
	
	/**
	 * \name fire
	 * \param Worker 해고될 워커.
	 * 
	 * 워커를 제거한다.
	 * 
	 * \return 
	 * 
	 * 성공할 경우 RETURN_OK, 
	 * 실패할 경우 RETURN_OK가 아닌 값.
	 */
	virtual ResultOf fire(GroupWorker* Worker);
	
// Member
protected:
	/**
	 * 태스크 큐.
	 */
	BlockingQueue* QueueOfTask;
	
	/**
	 * 펙토리 관리에 필요한 정보를 담는다.
	 */
	Group* InfoOfFactory;
	
	/**
	 * Running
	 */
	bool Running;
	
	/**
	 * Watchdog 스레드의 아이디.
	 */
	pthread_t TIdOfWatchdog;
	
	/**
	 * 감시 주기.
	 */
	USNumber IntervalOfWatch;
	
	/**
	 * 동작 시간.
	 */
	Stopwatch RunTime;
	
	/**
	 * 인스턴스의 상태를 나타낸다.
	 * TRUE일 경우 정상, FALSE일 경우 비정상.
	 */
	bool State;
};

#endif //FACTORY_CORE_H_